package com.ccubee.data.transfer.properties;

import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
import com.ccubee.data.transfer.utils.StringUtils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.NestedConfigurationProperty;

import java.util.Collections;
import java.util.Map;
import java.util.Objects;

/**
 * @Author ycf
 * @Date 2022/5/21 23:51
 * @Version 1.0
 */
@Data
public class CanalClientProperties {
    public static final String PREFIX = "csap.data.canal";
    /**
     * k1 实例名称
     * k2 is 源数据库名称
     * value 数据库连接 配置
     */
    private Map<String, Map<String, DbMapping>> instance = Collections.emptyMap();
    /**
     * 服务端信息
     */
    @NestedConfigurationProperty
    private TcpServerProperties tcpServer;

    /**
     * 不存在监听的类型是否打印日志
     */
    private Boolean eventTypeLog = true;
    /**
     * 是否可用
     */
    private Boolean enabled = Boolean.FALSE;
    /**
     * 时间
     */
    private Long loopTime = 1000L;

    /**
     * 映射
     *
     * @param destination  实例名称
     * @param sourceDbName 源数据库名称
     * @return 数据源
     */
    public DbMapping dbMapping(String destination, String sourceDbName) {
        if (!instance.containsKey(Objects.requireNonNull(destination))) {
            throw ExceptionUtils.mpe(String.format("instance not exits：%s", destination));
        }
        if (!instance.get(destination).containsKey(sourceDbName)) {
            throw ExceptionUtils.mpe(String.format("source dataBase not config：%s", sourceDbName));
        }
        return instance.get(destination).get(sourceDbName);
    }

    /**
     * 是否存在配置的数据库
     *
     * @param destination  实例名称
     * @param sourceDbName 源数据库名称
     * @return 数据源
     */
    public boolean containsDbMapping(String destination, String sourceDbName) {
        if (!instance.containsKey(Objects.requireNonNull(destination))) {
            return false;
        }
        if (!instance.get(destination).containsKey(sourceDbName)) {
            return false;
        }
        return true;
    }

    /**
     * 是否存在配置的数据库
     *
     * @param destination  实例名称
     * @param sourceDbName 源数据库名称
     * @return 数据源
     */
    public boolean containsTable(String destination, String sourceDbName, String tableName) {
        if (!instance.containsKey(Objects.requireNonNull(destination))) {
            return false;
        }
        Map<String, DbMapping> stringDbMappingMap = instance.get(destination);
        if (!stringDbMappingMap.containsKey(sourceDbName)) {
            return false;
        }
        return stringDbMappingMap.get(sourceDbName).contains(tableName);
    }

    /**
     * 是否存在配置的数据库
     *
     * @param destination  实例名称
     * @param sourceDbName 源数据库名称
     * @return 数据源
     */
    public TableMapping getTableMapping(String destination, String sourceDbName, String tableName) {
        if (!instance.containsKey(Objects.requireNonNull(destination))) {
            return null;
        }
        Map<String, DbMapping> stringDbMappingMap = instance.get(destination);
        if (!stringDbMappingMap.containsKey(sourceDbName)) {
            return null;
        }
        return stringDbMappingMap.get(sourceDbName).getMapping(tableName);
    }

    /**
     * 是否存在配置的数据库
     *
     * @param destination  实例名称
     * @param sourceDbName 源数据库名称
     * @return 数据源
     */
    public DbMapping getDbMapping(String destination, String sourceDbName) {
        if (!instance.containsKey(Objects.requireNonNull(destination))) {
            return null;
        }
        Map<String, DbMapping> stringDbMappingMap = instance.get(destination);
        if (!stringDbMappingMap.containsKey(sourceDbName)) {
            return null;
        }
        return stringDbMappingMap.get(sourceDbName);
    }

    /**
     * 数据库映射
     */
    @Data
    public static class DbMapping {
        /**
         * 目标数据库名称
         */
        private String dbName;
        /**
         * 数据源名称
         */
        private String dataSource;
        /**
         * k is sourceTable 源数据表格名称
         * 表格映射 可不配置（默认已源数据表格名称为主）
         */
        private Map<String, TableMapping> tables = Collections.emptyMap();

        /**
         * 是否存在配置
         *
         * @param sourceTable 源数据表名称
         * @return 是否存在
         */
        public boolean contains(String sourceTable) {
            return tables.containsKey(sourceTable);
        }

        public String getDbName(String targetDbName) {
            return StringUtils.isEmpty(this.dbName) ? targetDbName : this.dbName;
        }

        /**
         * 获取表格映射
         *
         * @param tableName 表名称
         * @return 结果
         */
        public TableMapping getMapping(String tableName) {
            return tables.get(tableName);
        }
    }

    /**
     * 表映射
     */
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode(callSuper = true)
    public static class TableMapping extends EventTypeProperties {
        public static final TableMapping TABLE = new TableMapping();
        /**
         * 目标数据表格名称
         */
        private String tableName;
        /**
         * 批处理条数
         */
        private int batchSize;
        /**
         * 字段映射，默认eq匹配
         */
        private Map<String, String> columns = Collections.emptyMap();

        /**
         * 是否存在配置
         *
         * @param sourceColumName 源数据字段名称
         * @return 是否存在
         */
        public boolean contains(String sourceColumName) {
            return columns.containsKey(sourceColumName);
        }

        /**
         * 获取表格名称
         *
         * @param targetTable 名称
         * @return 结果
         */
        public String getTableName(String targetTable) {
            return StringUtils.isEmpty(this.tableName) ? targetTable : this.tableName;
        }
    }
}
